
;;This module is the wrapper around srfi-18, replacing its function calls by logged ones.


(use-modules ((srfi srfi-18)
             #:renamer (symbol-prefix-proc 'original:)))
(use-modules
 (srfi srfi-9)
 (srfi srfi-1))

(include "bloom.scm")
(include "newmutex.scm") 

;TODO: mudar thread-specific
(define make-thread original:make-thread)
(define thread-sleep! original:thread-sleep!)
(define thread-specific original:thread-specific)
(define thread-specific-set! original:thread-specific-set!)
(define mutex-specific original:mutex-specific)
(define mutex-specific-set! original:mutex-specific-set!)
(define seconds->time original:seconds->time)
(define time->seconds original:time->seconds)
(define thread-start! original:thread-start!)
(define thread-name original:thread-name)
(define thread-join! original:thread-join!)


;srfi reimplementations
(define make-mutex
  (lambda args
    (let
	((m (apply original:make-mutex args))
	 (log (list (current-thread) 'mutex-created (current-time)))
	 (newmutex '()))

      (set! newmutex (make-new-mutex m (list log) 0 (new-bloom)))
      (original:mutex-specific-set! m (threadnumber))
      (add-to-global-log! newmutex)
      newmutex)))

(define mutex-lock!
  (lambda args
    (letrec
	((m (car args))
	 (rest (cdr args))
	 (thread (current-thread)))
      (log! m thread 'lock-try)
      ;copia dependencia do dono da mutex no próprio digest, adicionando a si proprio
      (set-digest! thread
		   (add-to-bloom! thread (bloom-copy (get-owner-digest m))))
      ;verifica se está no digest do owner
      (if
       (value-in-bloom thread (get-owner-digest m))
       ;TODO deadlock treatment
       (begin
	 (deadlock-proc)
	 (exit))
       (begin
	 ;seta a si mesmo como dono
	 (set-owner-digest! m (fetch-digest! thread))

	 (apply original:mutex-lock! (cons (get-mutex m) rest))
	 (log! m thread 'lock-acquire)
	 m)))))

(define mutex-unlock!
  (lambda args
    (let ((thread (thread-name (current-thread)))
	  (mutex (car args)))

      (log! mutex thread 'unlock-try)
      (original:mutex-unlock! (get-mutex mutex))
      (log! mutex thread 'unlock-success))))


(define (restablish-srfi-18!)
;replaces scpfdd functions by the srfi-18 ones
  (set! mutex-lock! original:mutex-lock!)
  (set! mutex-unlock! original:mutex-unlock!)
  (set! make-condition-variable original:make-condition-variable)
  (set! make-mutex original:make-mutex))

(define fetch-digest!
  (lambda (thread)
    (if ;não existe ou é lista nula
     (or (not (original:thread-specific thread)) (null? (original:thread-specific thread)))
     (original:thread-specific-set! thread (new-bloom))
     (original:thread-specific thread))))

(define deadlock-proc
  ;procedure to be called in case of deadlock
  (lambda ()
    (display "Deadlock detected! \n")))

(define set-deadlock-procedure!
  (lambda (proc)
    (set! deadlock-proc proc)))

(define set-digest!
  (lambda (t v)
    (fetch-digest! t)
    (vector-move-left! v 0 (1- (vector-length v)) (original:thread-specific t) 0)))


